/*
 * $QNXtpLicenseC:
 * Copyright 2007, QNX Software Systems. All Rights Reserved.
 * 
 * You must obtain a written license from and pay applicable license fees to QNX 
 * Software Systems before you may reproduce, modify or distribute this software, 
 * or any work that includes all or part of this software.   Free development 
 * licenses are available for evaluation and non-commercial purposes.  For more 
 * information visit http://licensing.qnx.com or email licensing@qnx.com.
 *  
 * This file may contain contributions from others.  Please review this entire 
 * file for other proprietary rights or license notices, as well as the QNX 
 * Development Suite License Guide at http://licensing.qnx.com/license-guide/ 
 * for other information.
 * $
 */





/* $Source$
 *
 * $Revision: 153052 $
 *
 * replace.c - regular expression pattern replacement functions
 *
 * DESCRIPTION
 *
 *	These routines provide for regular expression file name replacement
 *	as required by pax.
 *
 * AUTHORS
 *
 *	Mark H. Colburn, NAPS International
 *
 * Sponsored by The USENIX Association for public distribution. 
 *
 * Copyright (c) 1989 Mark H. Colburn.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms are permitted
 * provided that the above copyright notice is duplicated in all such 
 * forms and that any documentation, advertising materials, and other 
 * materials related to such distribution and use acknowledge that the 
 * software was developed * by Mark H. Colburn and sponsored by The 
 * USENIX Association. 
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 *
 * $Log$
 * Revision 1.5  2005/06/03 01:37:53  adanko
 * Replace existing QNX copyright licence headers with macros as specified by
 * the QNX Coding Standard. This is a change to source files in the head branch
 * only.
 *
 * Note: only comments were changed.
 *
 * PR25328
 *
 * Revision 1.4  2003/08/27 18:16:57  martin
 * Add QSSL Copyright to cover QNX contributions.
 *
 * Revision 1.3  2003/06/27 17:56:13  hsbrown
 * Fixed a problem with pax adding extra characters to path names.
 * PR#15557
 *
 * Revision 1.2  1996/07/30 15:08:33  garry
 * regex with a global replace was broken, s/ab/abc/g would
 * start at the beginning of the string after each replacement
 *
 * Revision 1.1  1996/07/29 15:50:46  garry
 * Initial revision
 *
 * Revision 1.2  89/02/12  10:05:59  mark
 * 1.2 release fixes
 * 
 * Revision 1.1  88/12/23  18:02:36  mark
 * Initial revision
 * 
 */

#ifndef lint
static char *ident = "$Id: replace.c 153052 2008-08-13 01:17:50Z coreos $";
static char *copyright = "Copyright (c) 1989 Mark H. Colburn.\nAll rights reserved.\n";
#endif /* not lint */

/* Headers */

#include "pax.h"


/* add_replstr - add a replacement string to the replacement string list
 *
 * DESCRIPTION
 *
 *	Add_replstr adds a replacement string to the replacement string
 *	list which is applied each time a file is about to be processed.
 *
 * PARAMETERS
 *
 *	char	*pattern	- A regular expression which is to be parsed
 */

#ifdef __STDC__

void add_replstr(char *pattern)

#else

void add_replstr(pattern)
char           *pattern;

#endif
{
    char           *p;
    char            sep;
    Replstr        *rptr;
    int             len;

    if ((len = strlen(pattern)) < 4) {
	fatal("Replacement string not added : "
		 "Malformed substitution syntax");
	return;
    }
    if ((rptr = (Replstr *) malloc(sizeof(Replstr))) == (Replstr *)NULL) {
	fatal("Replacement string not added : " "No space");
	return;
    }

    /* First character is the delimiter... */
    sep = *pattern;

    rptr->global = rptr->print = 0;
    /* Get trailing g and/or p */
    p = pattern + len - 1;
    while (*p != sep) {
	if (*p == 'g') {
            rptr->global = 1;
	} else if (*p == 'p') {
	    rptr->print = 1;
	} else {
	    warn(p, "Invalid RE modifier");
	}
	p--;
    }

    if (*p != sep) {
	fatal("Replacement string not added : " "Bad delimiters");
	free(rptr);
	return;
    }
    /* strip off leading and trailing delimiter */
    *p = '\0';
    pattern++;

    /* find the separating '/' in the pattern */
    p = pattern;
    while (*p) {
	if (*p == sep) {
	    break;
	}
	if (*p == '\\' && *(p + 1) != '\0') {
	    p++;
	}
	p++;
    }
    if (*p != sep) {
	fatal("Replacement string not added : " "Bad delimiters");
	free(rptr);
	return;
    }
    *p++ = '\0';

    /*
     * Now pattern points to 'old' and p points to 'new' and both are '\0'
     * terminated 
     */
    if ((rptr->comp = regcomp(pattern)) == (regexp *)NULL) {
	fatal("Replacement string not added : " "Invalid RE");
	free(rptr);
	return;
    }
    rptr->replace = p;
    rptr->next = (Replstr *)NULL;
    if (rplhead == (Replstr *)NULL) {
	rplhead = rptr;
	rpltail = rptr;
    } else {
	rpltail->next = rptr;
	rpltail = rptr;
    }
}



/* rpl_name - possibly replace a name with a regular expression
 *
 * DESCRIPTION
 *
 *	The string name is searched for in the list of regular expression
 *	substituions.  If the string matches any of the regular expressions
 *	then the string is modified as specified by the user.
 *
 * PARAMETERS
 *
 *	char	*name	- name to search for and possibly modify
 */

#ifdef __STDC__

void rpl_name(char *name)

#else

void rpl_name(name)
char           *name;

#endif
{
    int             found = 0;
    int             ret, hb;
    Replstr        *rptr;
    char            buff[PATH_MAX + 1];
    char            buff1[PATH_MAX + 1];
    char            buff2[PATH_MAX + 1];
    char           *p;
    char           *b;
    char           *wheretolook;

    strcpy(buff, name);
	hb = strlen (name);
    wheretolook=buff;
    for (rptr = rplhead; !found && rptr != (Replstr *)NULL; rptr = rptr->next) {
	do {
	    if ((ret = regexec(rptr->comp, wheretolook)) != 0) {
		wheretolook=rptr->comp->startp[0]+strlen(rptr->replace);
		p = buff;
		b = buff1;
		while (p < rptr->comp->startp[0]) {
		    *b++ = *p++;
		}
		p = rptr->replace;
		while (*p) {
		    *b++ = *p++;
		}
		strcpy(b, rptr->comp->endp[0]);
		found = 1;
		regsub(rptr->comp, buff1, buff2);
		strcpy(buff, buff2);
	    }
	} while (ret && rptr->global);
	if (found) {
	    if (rptr->print) {
		fprintf(stderr, "%s >> %s\n", name, buff);
	    }
		memset (name, 0, hb);
	    strcpy(name, buff);
	}
    }
}


/* get_disposition - get a file disposition
 *
 * DESCRIPTION
 *
 *	Get a file disposition from the user.  If the user enters 'y'
 *	the the file is processed, anything else and the file is ignored.
 *	If the user enters EOF, then the PAX exits with a non-zero return
 *	status.
 *
 * PARAMETERS
 *
 *	char	*mode	- string signifying the action to be taken on file
 *	char	*name	- the name of the file
 *
 * RETURNS
 *
 *	Returns 1 if the file should be processed, 0 if it should not.
 */

#ifdef __STDC__

int get_disposition(char *mode, char *name)

#else

int get_disposition(mode, name)
char	*mode;
char	*name;

#endif
{
    char	ans[2];
    char	buf[PATH_MAX + 10];

    if (f_disposition) {
	sprintf(buf, "%s %s? ", mode, name);
	if (nextask(buf, ans, sizeof(ans)) == -1 || ans[0] == 'q') {
	    exit(0);
	}
	if (strlen(ans) == 0 || ans[0] != 'y') {
	    return(1);
	} 
    } 
    return(0);
}


/* get_newname - prompt the user for a new filename
 *
 * DESCRIPTION
 *
 *	The user is prompted with the name of the file which is currently
 *	being processed.  The user may choose to rename the file by
 *	entering the new file name after the prompt; the user may press
 *	carriage-return/newline, which will skip the file or the user may
 *	type an 'EOF' character, which will cause the program to stop.
 *
 * PARAMETERS
 *
 *	char	*name		- filename, possibly modified by user
 *	int	size		- size of allowable new filename
 *
 * RETURNS
 *
 *	Returns 0 if successfull, or -1 if an error occurred.
 *
 */

#ifdef __STDC__

int get_newname(char *name, int size)

#else

int get_newname(name, size)
char	*name;
int	size;

#endif
{
    char	buf[PATH_MAX + 10];

    if (f_interactive) {
	sprintf(buf, "rename %s? ", name);
	if (nextask(buf, name, size) == -1) {
	    exit(0);
	}
	if (strlen(name) == 0) {
	    return(1);
	}
    }
    return(0);
}
